﻿using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Windows;

namespace AutoCADDotNetLibrary
{
    /// <summary>
    /// 选择实体事件
    /// </summary>
    public class SelectEntityEvent
    {
        private class ConnectEvent
        {
            public ConnectEvent(IReadEntityEvent iReadEntityEvent)
            {
                IReadEntityEvent = iReadEntityEvent;
            }

            public bool IsConnect { get; set; } = true;

            public IReadEntityEvent IReadEntityEvent { get; set; }
        }

        //目的：选择一次时，AutoCAD会多次调用此函数，_count解决此问题。
        //无法解决的问题，再一次选择很多时，AutoCAD会先显示100，再显示1000，再是全部，100和1000数量只是虚数。意思为还是会产生多次运行的情况。
        private static int _count = 0;
        /// <summary>
        /// 选择时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void SelectEntity(object sender, PromptSelectionResultEventArgs e)
        {
            Editor ed = (Editor)sender;

            PromptSelectionResult psr = e.Result;
            if (psr.Status != PromptStatus.OK)
                return;
            SelectionSet ss = psr.Value;

            if (ss.Count == _count)//数量是否变化，变化时，执行函数并记录数量。
            {
                return;
            }
            _count = ss.Count;

            List<KeyValuePair<string, ConnectEvent>> temp = _keys
                .Where(x => x.Value.IsConnect && x.Value.IReadEntityEvent != null && x.Value.IReadEntityEvent.IsUseEvent).ToList();
            if (temp.Count == 0)
                return;
            using (Transaction trans = ed.Document.TransactionManager.StartTransaction())
            {
                Entity[] ents = ss.Cast<SelectedObject>().Select(x => trans.GetObject(x.ObjectId, OpenMode.ForRead)).OfType<Entity>().ToArray();

                foreach (KeyValuePair<string, ConnectEvent> item in temp)
                {
                    item.Value.IReadEntityEvent.ReadEntities(ed.Document, ents);
                }
            }
        }

        /// <summary>
        /// 结束选择时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void EndingSelect(object sender, PromptForSelectionEndingEventArgs e)
        {
            if (e.Selection.Count == 0)
            {
                if (_count == 0)
                {
                    return;
                }
                _count = 0;

                Editor ed = (Editor)sender;

                List<KeyValuePair<string, ConnectEvent>> temp = _keys
                 .Where(x => x.Value.IsConnect && x.Value.IReadEntityEvent != null && x.Value.IReadEntityEvent.IsUseEvent).ToList();
                if (temp.Count == 0)
                    return;
                foreach (KeyValuePair<string, ConnectEvent> item in temp)
                {
                    item.Value.IReadEntityEvent.ReadEntities(ed.Document, new Entity[] { });
                }
            }
        }

        private static Dictionary<string, ConnectEvent> _keys = new Dictionary<string, ConnectEvent>();
        private static bool IsAddEvent = false;

        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="eventName">读取实体接口</param>
        /// <param name="iSelectEntityEvent">事件名称</param>
        public static void Add(string eventName, IReadEntityEvent iSelectEntityEvent)
        {
            _keys.Add(eventName, new ConnectEvent(iSelectEntityEvent));

            if (!IsAddEvent)
            {
                Application.DocumentManager.SetDocumentEvent(nameof(SelectEntityEvent), x =>
                {
                    x.Editor.PromptedForSelection += SelectEntity;//选择时，显示值
                    x.Editor.PromptForSelectionEnding += EndingSelect;//选择结束时，取消显示
                },
                x =>
                {
                    x.Editor.PromptedForSelection -= SelectEntity;
                    x.Editor.PromptForSelectionEnding -= EndingSelect;
                });

                Application.DocumentManager.AddDocumentEvent(nameof(SelectEntityEvent));

                IsAddEvent = true;
            }
        }

        /// <summary>
        /// 添加PaletteSet的StateChange显示
        /// </summary>
        /// <param name="ps">面板</param>
        /// <param name="eventName">事件名称</param>
        public static void SetStateChanged(PaletteSet ps, string eventName)
        {
            ps.StateChanged += (sender, e) =>
            {
                if (e.NewState == StateEventIndex.Show)
                {
                    Add(eventName);
                }
                else if (e.NewState == StateEventIndex.Hide)
                {
                    Remove(eventName);
                }
            };
        }

        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        public static void Add(string eventName)
        {
            if (_keys.ContainsKey(eventName))
            {
                _keys[eventName].IsConnect = true;
            }
        }

        /// <summary>
        /// 移除事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        public static void Remove(string eventName)
        {
            if (_keys.ContainsKey(eventName))
            {
                _keys[eventName].IsConnect = false;
            }
        }
    }
}
